
import { _decorator, Node, Size, Sprite, UITransform, Vec2, Vec3, Animation, v2, AnimationClip, ProgressBar } from 'cc';
import { MonsterManager } from '../monster/MonsterManager';
import { FightControl, GameState } from '../FightControl';
import { Loader } from '../../tools/LoadManger';
import { bulletManger } from '../bullet/BulletManager';
import { Move } from '../component/Move';
import { MonsterOrigin } from '../monster/MonsterOrigin';
import { Tools } from '../../tools/Tools';
import { DataHelper } from '../../system/DataHelper';
import { GunOrigin } from './GunOrigin';
import EvtManger from '../../tools/EvtManger';
import { AppControll, ConfigKey, EventName, PopView, tasteMainGun_config } from '../../manager/AppControll';
import { GameData } from '../../system/GameData';
import { PopManager } from '../../manager/PopManager';
import { UsingAgain } from '../../pop/UsingAgain';
import { SoundManager } from '../../manager/SoundManger';
const { ccclass, property } = _decorator;

@ccclass('MainGun')
export class MainGun extends GunOrigin {
    private mNdMount: Node = null;
    private mCurHitTime: number = null;
    private mCurHitPoint: any = null;
    private mNdGuide: Node = null;
    private mTasterTime = 0;
    private mBIsTaster = false;
    private mCurTasterConfig: tasteMainGun_config = null;
    private mNdTastCountDown = null;
    private mNdLevelUp = null; //主炮升级动画


    protected onLoad(): void {
        this.mNdMount = this.node.getChildByName("gunMount");
        this.mNdGun = this.node.getChildByName("gun");
        this.mNdGuide = this.node.getChildByName("guide");
        this.mNdTastCountDown = this.node.getChildByName("tryCountDown");
        this.mNdLevelUp = this.node.getChildByName("levelUp");
        this.RegisteredEvent();
        this.InitMainGun()
        this.mNdGun.getChildByName("muzzle").getComponent(Animation).on(Animation.EventType.FINISHED, () => {
            this.mNdGun.getChildByName("muzzle").active = false;
        })
        
        let an = this.mNdLevelUp.getComponent(Animation);
        Loader.LoadEffectImageDir(GameData.mainGunlevelUpAn, (arr) => {
            if (!arr) return;
            const clip = AnimationClip.createWithSpriteFrames(arr, arr.length);
            clip.name = "levelUp";
            clip.wrapMode = AnimationClip.WrapMode.Normal;
            an.addClip(clip);
        })
    }

    CloseToast() {
        this.mBIsTaster = false;
        this.mNdTastCountDown.active = false;
        this.InitMainGun();
    }

    PlayLevelUp() {
        let an = this.mNdLevelUp.getComponent(Animation);
        an.play("levelUp");
    }

    InitMainGun() {
        let gunConfig = DataHelper.GetAttack();

        this.mNdMount.getComponent(UITransform).contentSize = new Size(gunConfig.mainGunBottomSize[0], gunConfig.mainGunBottomSize[1]);
        this.mNdMount.position = new Vec3(gunConfig.gunBottomPosition[0], gunConfig.gunBottomPosition[1]);
        this.mNdGun.getChildByName("gunSp").getComponent(UITransform).anchorPoint = new Vec2(0.5, 0.3);
        
        let path = DataHelper.GetSkin_configById(GameData.playerData.curGunSkinId).mainGunSkinRes;
        Loader.LoadGunImage("mainGunSkin/" + path, (spf) => {
            this.mNdGun.getChildByName("gunSp").getComponent(Sprite).spriteFrame = spf;
            this.mNdGun.getChildByName("gunSp").getComponent(UITransform).contentSize = new Size(gunConfig.mainGunSize[0], gunConfig.mainGunSize[1]);
        });
        // Loader.LoadImage("image/gun/" + gunConfig.mainGunBottomRes, (spf) => {
        //     this.mNdMount.getComponent(Sprite).spriteFrame = spf;
        // });

        
        this.mNdGuide.active = GameData.playerData.IsNewPlayer;

        let an = this.mNdGun.getChildByName("muzzle").getComponent(Animation);
        this.mNdGun.getChildByName("muzzle").position = new Vec3(gunConfig.gunFirePosition[0], gunConfig.gunFirePosition[1]);
        this.mNdGun.getChildByName("muzzle").getComponent(UITransform).contentSize = new Size(gunConfig.gunFireSize[0], gunConfig.gunFireSize[1]);
        Loader.LoadMuzzleImageDir("mainGunFire", (arr) => {
            const clip = AnimationClip.createWithSpriteFrames(arr, 10);
            clip.name = "muzzle";
            clip.wrapMode = AnimationClip.WrapMode.Normal;
            clip.speed = gunConfig.gunFireAniSpeed;
            an.addClip(clip);
        })
    }

    Tick(dt) {
        if (GameData.isPause) return;


        if (FightControl.gameState == GameState.start) {

            this.FindTarget();

            if (this.mBIsTaster) {
                this.mTasterTime += dt;
                let countDown = GameData.curToastTotalTime - this.mTasterTime;
                this.mNdTastCountDown.getComponent(ProgressBar).progress = countDown / GameData.curToastTotalTime;
                if (countDown < 0) {
                    this.mBIsTaster = false;
                    this.mNdTastCountDown.active = false;
                    this.InitMainGun();
                    if (GameData.curToastTotalTime != Number.parseInt(DataHelper.GetConfigByKey(ConfigKey.tasteGunVideoTime).value)) {
                        PopManager.Instance<PopManager>().ShowPop(PopView.usingAgain, (node) => {
                            node.getComponent(UsingAgain).InitUsingAgain(this.mCurTasterConfig);
                        });
                    }
                }
            }
            if (!this.mTarget) return;
            let direction = null;
            let bulletId = DataHelper.GetAttack().bullet;
            let sp0 = DataHelper.GetBulletConfig(bulletId).moveSpeed;
            this.barrelLength = DataHelper.GetBulletConfig(bulletId).firePosition;
            this.mCurHitTime = Tools.GetHitTime(sp0, this.mTarget, this.node.position, this.barrelLength);
            this.mCurHitPoint = this.GetHitPositinByTime(this.mCurHitTime);
            if (this.mCurHitPoint) direction = new Vec3(this.mCurHitPoint.x, this.mCurHitPoint.y, 0).subtract(this.node.position).normalize();
            if (!this.mCurHitPoint) return;
            //计算方向向量与x轴正方向的夹角
            let angle = new Vec2(1, 0).angle(new Vec2(direction.x, direction.y));
            //将夹角转换为欧拉角，并将其应用于当前节点的旋转组件上
            this.mNdGun.eulerAngles = new Vec3(0, 0, angle / Math.PI * 180 - 90);

            this.mCurTime += dt;
            let attackInterva = DataHelper.GetAutoSpeed();
            if (!attackInterva) return;
            if (this.mCurTime >= (attackInterva.attributeNum - DataHelper.GetSkinAttackInterval())) {
                this.mCurTime = 0;
                let index = Tools.GetLtMonster().length;
                if (index > 0) index = index - 1;
                this.mTarget.setSiblingIndex(index);
                if (this.mBIsTaster) {
                    this.TasterGunShoot();
                } else {
                    this.Shoot();
                }
            }
        }
    }

    RegisteredEvent() {
        super.RegisteredEvent();
        EvtManger.on(EventName.lockMonsterByTouch, this, this.LockByTouch);
        EvtManger.on(EventName.shootByTouch, this, this.shootByTouch);
        EvtManger.on(EventName.tasteGun, this, this.TasteGun);
        EvtManger.on(EventName.mainGunLevelUp, this, this.PlayLevelUp);
        EvtManger.on(EventName.updateUsingSkin, this, this.updateUsingSkin);
        EvtManger.on(EventName.levelChallenge, this, this.ModelChange);
        EvtManger.on(EventName.normalChanllenge, this, this.ModelChange)
    }

    ModelChange() {
        this.mTarget = null;
        this.CloseToast();
    }

    updateUsingSkin() {
        if (this.mBIsTaster) return;
        let path = DataHelper.GetSkin_configById(GameData.playerData.curGunSkinId).mainGunSkinRes;
        Loader.LoadGunImage("mainGunSkin/" + path, (spf) => {
            this.mNdGun.getChildByName("gunSp").getComponent(Sprite).spriteFrame = spf;
        });
    }

    shootByTouch() {
        if (this.mBIsTaster) {
            this.TasterGunShoot();
        } else {
            this.Shoot();
        }
    }

    TasteGun(config: tasteMainGun_config, totalTime: number) {
        this.mBIsTaster = true;
        this.mCurTasterConfig = config;
        this.mNdTastCountDown.active = true;
        this.mTasterTime = 0;
        GameData.curToastTotalTime = totalTime;
        this.ShowTasteGun();
    }

    ShowTasteGun() {
        
        this.mNdGun.getChildByName("gunSp").getComponent(UITransform).contentSize = new Size(this.mCurTasterConfig.gunSize[0], this.mCurTasterConfig.gunSize[1]);
        this.mNdMount.getComponent(UITransform).contentSize = new Size(this.mCurTasterConfig.gunBottomSize[0], this.mCurTasterConfig.gunBottomSize[1]);
        this.mNdMount.position = new Vec3(this.mCurTasterConfig.gunBottomPosition[0], this.mCurTasterConfig.gunBottomPosition[1]);
        this.mNdGun.getChildByName("gunSp").getComponent(UITransform).anchorPoint = new Vec2(this.mCurTasterConfig.gunAnchorPoint[0], this.mCurTasterConfig.gunAnchorPoint[1]);
        this.mNdGun.getChildByName("muzzle").position = new Vec3(this.mCurTasterConfig.gunFirePosition[0], this.mCurTasterConfig.gunFirePosition[1]);

        Loader.LoadImage("image/gun/" + this.mCurTasterConfig.gunRes, (spf) => {
            this.mNdGun.getChildByName("gunSp").getComponent(Sprite).spriteFrame = spf;
        });

        Loader.LoadImage("image/gun/" + this.mCurTasterConfig.gunBottomRes, (spf) => {
            this.mNdMount.getComponent(Sprite).spriteFrame = spf;
        });

        let bulletID = this.mCurTasterConfig.bulletId;
        let bulletConfig = DataHelper.GetBulletConfig(Number.parseInt(bulletID));

        let an = this.mNdGun.getChildByName("muzzle").getComponent(Animation);
        this.mNdGun.getChildByName("muzzle").getComponent(UITransform).contentSize = new Size(this.mCurTasterConfig.gunFireSize[0], this.mCurTasterConfig.gunFireSize[1]);
        Loader.LoadMuzzleImageDir(bulletConfig.bulletFlash, (arr) => {
            const clip = AnimationClip.createWithSpriteFrames(arr, arr.length);
            clip.name = bulletConfig.bulletFlash;
            clip.wrapMode = AnimationClip.WrapMode.Normal;
            clip.speed = this.mCurTasterConfig.gunFireAniSpeed;
            an.addClip(clip);
        });
    }

    protected onDestroy(): void {
        EvtManger.off(EventName.lockMonsterByTouch, this, this.LockByTouch);
        EvtManger.off(EventName.shootByTouch, this, this.Shoot);
    }

    LockByTouch(node: Node) {

        if (!this.mTarget) return;

        //将上一个锁定目标切位普通状态
        if (this.mTarget.getComponent(MonsterOrigin)) {
            this.mTarget.getComponent(MonsterOrigin).BeNormal();
        }
        //切换锁定目标
        this.mTarget = node;
        this.mTarget.getComponent(MonsterOrigin).BeLock();
        let direction = null;
        let bulletId = DataHelper.GetAttack().bullet;
        let sp0 = DataHelper.GetBulletConfig(bulletId).moveSpeed;
        this.barrelLength = DataHelper.GetBulletConfig(bulletId).firePosition;
        this.mCurHitTime = Tools.GetHitTime(sp0, this.mTarget, this.node.position, this.barrelLength);
        this.mCurHitPoint = this.GetHitPositinByTime(this.mCurHitTime);
        if (this.mCurHitPoint) direction = new Vec3(this.mCurHitPoint.x, this.mCurHitPoint.y, 0).subtract(this.node.position).normalize();
        if (!this.mCurHitPoint) return;
        //计算方向向量与x轴正方向的夹角
        let angle = new Vec2(1, 0).angle(new Vec2(direction.x, direction.y));
        //将夹角转换为欧拉角，并将其应用于当前节点的旋转组件上
        this.mNdGun.eulerAngles = new Vec3(0, 0, angle / Math.PI * 180 - 90);
        EvtManger.do(EventName.setTarget, this.mTarget);
    }

    Shoot() {
        this.mNdGun.getChildByName("muzzle").active = true;
        if (GameData.playerData.IsNewPlayer) {
            GameData.playerData.IsNewPlayer = false;
            this.mNdGuide.active = false;
            AppControll.Platform.SendBuryPoint(100009);
        }

        if (!this.mTarget) return;
        this.node.getComponent(Animation).play();
        this.mNdGun.getChildByName("muzzle").getComponent(Animation).play("muzzle");
        let point = this.mCurHitPoint;
        let t = this.mCurHitTime;
        
        if (!point) return;


        let bulletId = DataHelper.GetAttack().bullet;
        this.barrelLength = DataHelper.GetBulletConfig(bulletId).firePosition;
        let x = this.barrelLength * Math.cos((this.mNdGun.eulerAngles.z + 90) * Math.PI / 180);
        let y = this.barrelLength * Math.sin((this.mNdGun.eulerAngles.z + 90) * Math.PI / 180);
        let startPoint = new Vec3(x, y + this.node.position.y);

        let skinDmg = DataHelper.GetSkinBuffDmg();
        let atk = DataHelper.GetAttack().attributeNum;
        atk = atk + atk * (skinDmg - 1);
        
        let chtRate = DataHelper.GetCriticalHitRate().attributeNum;
        let chtdmg = DataHelper.GetCriticalHitDamage().attributeNum;
        let damageBoost = DataHelper.GetDamageBoost().attributeNum;
        let dmg = Tools.CalculateDamage(atk, chtRate, chtdmg, damageBoost, t);
        let bulletConfig = DataHelper.GetBulletConfig(bulletId);
        SoundManager.Instance<SoundManager>().PlayEffect("gun/" + bulletConfig.bulletAudio, Number.parseFloat(DataHelper.GetConfigByKey(ConfigKey.gunVolume).value));
        let euler = this.mNdGun.eulerAngles.clone().subtract(new Vec3(0, 0, 0));
        this.mTarget.getComponent(MonsterOrigin).Attacked(dmg);
        bulletManger.CreateBullet(bulletId, euler, startPoint, new Vec3(point.x, point.y));
    }

    TasterGunShoot() {
        this.mNdGun.getChildByName("muzzle").active = true;
        if (GameData.playerData.IsNewPlayer) {
            GameData.playerData.IsNewPlayer = false;
            this.mNdGuide.active = false;
        }
        
        if (!this.mTarget) return;
        let point = this.mCurHitPoint;
        if (!point) return;

        let mainGunBullet = DataHelper.GetAttack().bullet;

        this.barrelLength = DataHelper.GetBulletConfig(mainGunBullet).firePosition;

        let x = this.barrelLength * Math.cos((this.mNdGun.eulerAngles.z + 90) * Math.PI / 180);
        let y = this.barrelLength * Math.sin((this.mNdGun.eulerAngles.z + 90) * Math.PI / 180);

        let startPoint = new Vec3(x, y + this.node.position.y);

        let euler = this.mNdGun.eulerAngles.clone().subtract(new Vec3(0, 0, 0));

        let bulletID = this.mCurTasterConfig.bulletId;
        let bulletConfig = DataHelper.GetBulletConfig(Number.parseInt(bulletID));
        SoundManager.Instance<SoundManager>().PlayEffect("gun/" + bulletConfig.bulletAudio, Number.parseFloat(DataHelper.GetConfigByKey(ConfigKey.gunVolume).value));
        this.mNdGun.getChildByName("muzzle").getComponent(Animation).play(bulletConfig.bulletFlash);
        bulletManger.CreateTasterBullet(Number.parseInt(bulletID), euler, startPoint, new Vec2(point.x, point.y), this.mCurTasterConfig, this.mTarget);
    }

    MonsterDrath(node: Node) {
        if (!this.mTarget) return;
        if (this.mTarget === node) {
            this.mTarget = null;
        }
    }

    //计算当前发出的子弹从预设的轨道击中怪物的时间
    GetHitTime(): number {
        let bulletId = DataHelper.GetAttack().bullet;
        let sp0 = DataHelper.GetBulletConfig(bulletId).moveSpeed;
        let sp1 = this.mTarget.getComponent(Move).Speed;
        let temp = this.mTarget.position.clone().subtract(this.node.position);
        let N = temp.length();
        let a = new Vec2(temp.x, temp.y);
        let b = this.mTarget.getComponent(Move).GetDirection();
        let cosθ = a.clone().dot(b.clone().multiplyScalar(-1)) / (a.length() * b.length());
        let ta = sp1 * sp1 - sp0 * sp0;
        let tb = cosθ * 2 * sp1 * N * -1;
        let tc = N * N;
        this.barrelLength = DataHelper.GetBulletConfig(bulletId).firePosition;
        let t = Tools.SolveQuadraticEquation(ta, tb, tc) - this.barrelLength / sp0;
        return t;
    }
}
